package com.trainoo.payment.mock.service;

import com.alibaba.fastjson.JSON;
import com.trainoo.payment.mock.cache.CacheMapService;
import com.trainoo.payment.mock.cache.LocalCache;
import com.trainoo.payment.mock.cache.PayerIdCache;
import com.trainoo.payment.mock.config.Config;
import com.trainoo.payment.mock.cache.OrderCache;
import com.trainoo.payment.mock.controller.PaymentController;
import com.trainoo.payment.mock.message.request.*;
import com.trainoo.payment.mock.message.response.*;
import com.trainoo.payment.mock.util.DateUtil;
import com.trainoo.payment.mock.util.TransIdUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * <p> add description here </p>
 *
 * @author tao.zhou
 * @version 1.0
 * @date 2021/12/1 20:05:00
 */
@Service
public class PaymentService {

    private static final Logger logger = LoggerFactory.getLogger(PaymentController.class);

    @Value("${code.gen.format}")
    private String format;
    @Resource
    private Config config;

    @Resource
    private CacheMapService cacheMapService;

    public QrUrlGenResponse qrUrlGen(QrUrlGenRequest request, String callBackUrl, String ip) {
        sleepSeconds();
        String codeUrl = String.format(format, request.getOutOrderNo(), callBackUrl);
        QrUrlGenResponse response = new QrUrlGenResponse();
        response.setCodeUrl(codeUrl);
        response.setTransId(TransIdUtil.getPayTransId());
        response.setOriOrderNo(request.getOutOrderNo());

        // 自动回调
        if (config.getAutoCallback()) {
            // 判断是否有黑名单
            if (config.notInBlackList(ip)) {
                logger.info("[{}]开始发起自动回调, 订单号[{}]", ip, request.getOutOrderNo());
                autoCallback(callBackUrl, TransIdUtil.getPayTransId(), response.getOriOrderNo(), config.getSleepTime());
                return response;
            }
        }

        // 不主动回调成功，需扫码后才返回成功
        logger.info("[{}]已设置成不主动回调, 订单号[{}]", ip, request.getOutOrderNo());
        OrderCache cache = new OrderCache();
        cache.setAmount(request.getOrderAmount());
        cache.setOrderNo(request.getOutOrderNo());
        cache.setCallbackUrl(callBackUrl);
        cacheMapService.set(cache.getOrderNo(), JSON.toJSONString(cache));
        return response;
    }

    public PayResponse qrPay(PayRequest request, String callBackUrl) {
        PayResponse response = new PayResponse();
        response.setOrigOrderNo(request.getOutOrderNo());
        response.setAmount(request.getOrderAmount());
        response.setTransId(TransIdUtil.getPayTransId());
        response.setPayTime(DateUtil.getYMDStr());
        response.setPayStatus(config.getCallbackResult());
        response.setPayerId("None");

        // 支付回调
        autoCallback(callBackUrl, response.getTransId(), response.getOrigOrderNo(), config.getSleepTime());
        return response;
    }

    public void autoCallback(String callBackUrl, String transId, String orderNo, Long sleepTime) {
        logger.info("开始发起自动回调, 订单号[{}], 延时[{}s]", callBackUrl, sleepTime/1000);
        PayNotifyThread thread = new PayNotifyThread(callBackUrl, transId, orderNo, sleepTime);
        new Thread(thread).start();
    }

    public PayStatusResponse payStatus(PayStatusRequest request) {
        PayStatusResponse response = new PayStatusResponse();
        response.setOrigOrderNo(request.getOutOrderNo());
        response.setTransId(request.getTransId());
        PayerIdCache payerIdCache = (PayerIdCache) LocalCache.getWithUpdateLastAccess(String.format(LocalCache.PAYER_INFO, request.getOutOrderNo()));
        if(payerIdCache != null){
            response.setFourthTransNo(payerIdCache.getFourthTransNo());
            response.setPayerId(payerIdCache.getPayerId());
        }
        // 缓存存在则说明没有扫码回调，此时不返回成功
        if (cacheMapService.isExist(request.getOutOrderNo())) {
            response.setPayStatus(Config.WAIT);
        } else {
            response.setPayStatus(Config.SUCCESS);
        }
        return response;
    }

    public RefundResponse refund(RefundRequest request) {
        RefundResponse response = new RefundResponse();
        response.setOrigOrderNo(request.getOrigOrderNo());
        response.setOrigTransId(request.getOrigTransId());
        response.setRefundTransId(TransIdUtil.getRefundTransId());
        response.setRefundAmount(request.getRefundAmount());
        return response;
    }

    public RefundStatusResponse refundStatus(RefundStatusRequest request) {
        RefundStatusResponse response = new RefundStatusResponse();
        response.setOrigOrderNo(request.getRefundNo());
        response.setRefundTransId(request.getRefundTransId());
        response.setRefundAmount(1L);
        response.setRefundStatus(config.getCallbackResult());
        return response;
    }

    public void doPay(String orderNo, String callbackUrl) {
        // 清空缓存
        cacheMapService.remove(orderNo);
        // 支付回调
        autoCallback(callbackUrl, TransIdUtil.getPayTransId(), orderNo, 0L);
    }

    private void sleepSeconds() {
        if (config.getDelay()) {
            try {
                logger.info("延迟返回开启，线程休眠[{}s]", config.getDelayTime() / 1000);
                Thread.sleep(config.getDelayTime());
            } catch (InterruptedException e) {
                logger.error("线程休眠异常", e);
            }
        }
    }
}
